package bavaria.hightech.banking;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.TimerTask;

import bavaria.hightech.comparators.CompEnum;
import bavaria.hightech.exceptions.FestgeldKontoNichtUeberziehbar;
import bavaria.hightech.konditionen.FestgeldKonditionen;
import bavaria.hightech.konditionen.GiroKonditionen;
import bavaria.hightech.konditionen.GiroZinsen;
import bavaria.hightech.konditionen.Laufzeit;
import bavaria.hightech.money.Money;
import bavaria.hightech.zeitgeber.Zeitgeber;

public class BankImpl implements BankKundenSicht, BankAdministration, B2B {

	private FestgeldKonditionen[] festkon;
	private GiroKonditionen[] girokon;
	private Hashtable<Integer, Konto> konten;
	private static Map <String,ResourceBundle> banklang;
	private int konto;
	private Zeitgeber zeitgeber;
	private static String locale;

	public BankImpl(String local) {
		locale = local;
		banklang = new HashMap<String, ResourceBundle>();
		banklang.put("DE", ResourceBundle.getBundle("statement_de_de", new Locale("de","de")));
		banklang.put("EN", ResourceBundle.getBundle("statement_en_en", new Locale("en","en")));
		konto = 1000;
		konten = new Hashtable<Integer, Konto>();
		festkon = new FestgeldKonditionen[3];
		girokon = new GiroKonditionen[3];
		festkon[0] = new FestgeldKonditionen(Laufzeit.EINS);
		festkon[1] = new FestgeldKonditionen(Laufzeit.DREI);
		festkon[2] = new FestgeldKonditionen(Laufzeit.ZWOELF);
		for (int x = 0; x < girokon.length; x++)
			girokon[x] = new GiroKonditionen(x + 1);

		zeitgeber = Zeitgeber.getInstance();
		zeitgeber.startVerzinsen(1, new TimerTask() {
			public void run() {
				try {
					BankImpl.this.verzinsen();
				} catch (FestgeldKontoNichtUeberziehbar e) {
					e.printStackTrace();
				}
			}
		});

	}

	public void aenderGiroZinsen(double hab, double soll) {
		GiroZinsen.getInstance().setGiroZinsen(hab, soll);
	}

	@Override
	public void FestgeldKontoErstellen(String name, Laufzeit laufzeit) {
		FestgeldKonto festkonto = new FestgeldKonto(konto, name,
				getfestkon(laufzeit));
		konten.put(konto, festkonto);
		konto++;
	}

	@Override
	public void GiroKontoErstellen(String name) {

		Random random = new Random();
		GiroKonto girokonto = new GiroKonto(konto, name,
				girokon[random.nextInt(3)]);
		konten.put(konto, girokonto);
		konto++;

	}

	public void verzinsen() throws FestgeldKontoNichtUeberziehbar {
		for (Map.Entry<Integer, Konto> e : konten.entrySet()) {
			konten.get(e.getKey()).verzinsen();
		}
	}

	@Override
	public void einzahlen(int kontonr, Money betrag, String grund) {
		getKonto(kontonr).einzahlen(betrag, grund);

	}

	@Override
	public void abheben(int kontonr, Money betrag, String grund)
			throws FestgeldKontoNichtUeberziehbar {
		getKonto(kontonr).abheben(betrag, grund);

	}

	@Override
	public void transaktion(int ausgangskontonr, int zielkontonr, Money betrag,
			String grund) throws FestgeldKontoNichtUeberziehbar {
		getKonto(ausgangskontonr).abheben(betrag, grund);
		getKonto(zielkontonr).einzahlen(betrag, grund);
	}

	@Override
	public void kontoauszug(int kontonr, CompEnum comp, String formatter, String path) {
		Statement stat = new Statement();
		stat.getFormatter(formatter).addInhaber(getKonto(kontonr));
		for(int x = 0; x < getKonto(kontonr).getBuchungsliste().size(); x++){
			stat.getFormatter(formatter).addBuchung(getKonto(kontonr).getBuchungsliste().get(x));
		}
		stat.getFormatter(formatter).getKontoauszug(path);
	}

	private Konto getKonto(int kontonr) {
		return konten.get(kontonr);
	}
	
	public static ResourceBundle getlang(){
		return banklang.get(locale);
	}

	@Override
	public long getKontostand(int kontonr) {
		return getKonto(kontonr).getKontostand().getBetrag();
	}

	private FestgeldKonditionen getfestkon(Laufzeit laufzeit) {
		if (laufzeit == Laufzeit.EINS) {
			return festkon[0];
		} else if (laufzeit == Laufzeit.DREI) {
			return festkon[1];
		} else
			return festkon[2];

	}

	@Override
	public void transaktion(String zielbank, int ausgangskontonr,
			int zielkontonr, Money betrag, String grund)
			throws FestgeldKontoNichtUeberziehbar {
		getKonto(ausgangskontonr).abheben(betrag, grund);
		((BankImpl) BankRegistry.getInstance().lookup(zielbank)).getKonto(
				zielkontonr).einzahlen(betrag, grund);

	}

}
